[IA64] SN2 polling console driver
authorAlex Williamson <alex.williamson@hp.com>
Thu, 24 May 2007 20:13:58 +0000 (14:13 -0600)
committerAlex Williamson <alex.williamson@hp.com>
Thu, 24 May 2007 20:13:58 +0000 (14:13 -0600)
First cut of super simple console driver with polled input support. In
addition switch driver to use ia64_sn_console_putb() post-boot to get
interactive response.

Signed-off-by: Jes Sorensen <jes@sgi.com>
xen/arch/ia64/xen/sn_console.c

index 0c596b3b1eae1b950d76001ac8f50582fba7d85c..6159016a5d0398d687f9c5a4535d25e9ae2a51bb 100644 (file)
@@ -8,19 +8,84 @@
 #include <asm/acpi.h>
 #include <asm/sn/sn_sal.h>
 #include <xen/serial.h>
+#include <xen/sched.h>
+
+struct sn_console_data {
+       struct timer timer;
+       unsigned int timeout_ms;
+       int booted;
+};
+
+static struct sn_console_data console_data = {
+       .timeout_ms = 8 * 16 * 1000 / 9600,
+};
+
 
 /*
  * sn_putc - Send a character to the console, polled or interrupt mode
  */
 static void sn_putc(struct serial_port *port, char c)
 {
-       ia64_sn_console_putc(c);
+       struct sn_console_data *sndata = port->uart;
+
+       if (sndata->booted)
+               ia64_sn_console_putb(&c, 1);
+       else
+               ia64_sn_console_putc(c);
 }
 
+/*
+ * sn_getc - Get a character from the console, polled or interrupt mode
+ */
+static int sn_getc(struct serial_port *port, char *pc)
+{
+       int ch;
+
+       ia64_sn_console_getc(&ch);
+       *pc = ch & 0xff;
+       return 1;
+}
+
+static void sn_endboot(struct serial_port *port)
+{
+       struct sn_console_data *sndata = port->uart;
+
+       sndata->booted = 1;
+}
+
+
+static void sn_poll(void *data)
+{
+       int ch, status;
+       struct serial_port *port = data;
+       struct sn_console_data *sndata = port->uart;
+       struct cpu_user_regs *regs = guest_cpu_user_regs();
+
+       status = ia64_sn_console_check(&ch);
+       if (!status && ch) {
+               serial_rx_interrupt(port, regs);
+       }
+       set_timer(&sndata->timer, NOW() + MILLISECS(sndata->timeout_ms));
+}
+
+
+static void sn_init_postirq(struct serial_port *port)
+{
+       struct sn_console_data *sndata = port->uart;
+
+        init_timer(&sndata->timer, sn_poll, port, 0);
+        set_timer(&sndata->timer, NOW() + MILLISECS(console_data.timeout_ms));
+}
+
+
 static struct uart_driver sn_sal_console = {
+       .init_postirq = sn_init_postirq,
        .putc = sn_putc,
+       .getc = sn_getc,
+       .endboot = sn_endboot,
 };
 
+
 /**
  * early_sn_setup - early setup routine for SN platforms
  *
@@ -45,8 +110,7 @@ static void __init early_sn_setup(void)
        efi_systab = (efi_system_table_t *) __va(ia64_boot_param->efi_systab);
        config_tables = __va(efi_systab->tables);
        for (i = 0; i < efi_systab->nr_tables; i++) {
-               if (efi_guidcmp(config_tables[i].guid, SAL_SYSTEM_TABLE_GUID) ==
-                   0) {
+               if (!efi_guidcmp(config_tables[i].guid, SAL_SYSTEM_TABLE_GUID)) {
                        sal_systab = __va(config_tables[i].table);
                        p = (char *)(sal_systab + 1);
                        for (j = 0; j < sal_systab->entry_count; j++) {
@@ -73,11 +137,11 @@ static void __init early_sn_setup(void)
  */
 int __init sn_serial_console_early_setup(void)
 {
-       if (strcmp("sn2",acpi_get_sysname()))
+       if (strcmp("sn2", acpi_get_sysname()))
                return -1;
 
        early_sn_setup();       /* Find SAL entry points */
-       serial_register_uart(0, &sn_sal_console, NULL);
+       serial_register_uart(0, &sn_sal_console, &console_data);
 
        return 0;
 }